package com.example.artemis.statistics;

import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 队列统计模型
 * 封装每个队列的统计数据
 */
public class QueueStatistics {

    private final String queueName;

    // 消息计数统计
    private final AtomicInteger sentCount = new AtomicInteger(0);
    private final AtomicInteger processedCount = new AtomicInteger(0);
    private final AtomicInteger failedCount = new AtomicInteger(0);
    private final AtomicInteger retriedCount = new AtomicInteger(0);

    // 时间统计
    private final AtomicLong totalProductionTime = new AtomicLong(0);
    private final AtomicLong totalProcessingTime = new AtomicLong(0);
    private final AtomicLong minProductionTime = new AtomicLong(Long.MAX_VALUE);
    private final AtomicLong maxProductionTime = new AtomicLong(0);
    private final AtomicLong minProcessingTime = new AtomicLong(Long.MAX_VALUE);
    private final AtomicLong maxProcessingTime = new AtomicLong(0);

    // 消费者活动统计
    private final ConcurrentHashMap<String, AtomicInteger> consumerActivity = new ConcurrentHashMap<>();

    // 最后活动时间
    private volatile LocalDateTime lastActivityTime;

    public QueueStatistics(String queueName) {
        this.queueName = queueName;
        this.lastActivityTime = LocalDateTime.now();
    }

    /**
     * 获取队列名称
     */
    public String getQueueName() {
        return queueName;
    }

    // ================== 发送统计 ==================

    /**
     * 增加发送计数
     */
    public void incrementSent() {
        sentCount.incrementAndGet();
        updateLastActivityTime();
    }

    /**
     * 增加发送计数（批量）
     */
    public void incrementSent(int count) {
        sentCount.addAndGet(count);
        updateLastActivityTime();
    }

    /**
     * 增加生产时间
     */
    public void addProductionTime(long time) {
        totalProductionTime.addAndGet(time);
        updateMinProductionTime(time);
        updateMaxProductionTime(time);
    }

    /**
     * 获取发送总数
     */
    public int getSentCount() {
        return sentCount.get();
    }

    /**
     * 获取平均生产时间
     */
    public double getAverageProductionTime() {
        int sent = sentCount.get();
        return sent > 0 ? (double) totalProductionTime.get() / sent : 0;
    }

    // ================== 处理统计 ==================

    /**
     * 增加处理计数
     */
    public void incrementProcessed() {
        processedCount.incrementAndGet();
        updateLastActivityTime();
    }

    /**
     * 增加失败计数
     */
    public void incrementFailed() {
        failedCount.incrementAndGet();
        updateLastActivityTime();
    }

    /**
     * 增加重试计数
     */
    public void incrementRetried() {
        retriedCount.incrementAndGet();
        updateLastActivityTime();
    }

    /**
     * 增加处理时间
     */
    public void addProcessingTime(long time) {
        totalProcessingTime.addAndGet(time);
        updateMinProcessingTime(time);
        updateMaxProcessingTime(time);
    }

    /**
     * 增加消费者活动
     */
    public void incrementConsumerActivity(String consumerId) {
        consumerActivity.computeIfAbsent(consumerId, k -> new AtomicInteger(0)).incrementAndGet();
        updateLastActivityTime();
    }

    // ================== 获取方法 ==================

    /**
     * 获取处理总数
     */
    public int getProcessedCount() {
        return processedCount.get();
    }

    /**
     * 获取失败总数
     */
    public int getFailedCount() {
        return failedCount.get();
    }

    /**
     * 获取重试总数
     */
    public int getRetriedCount() {
        return retriedCount.get();
    }

    /**
     * 获取平均处理时间
     */
    public double getAverageProcessingTime() {
        int processed = processedCount.get();
        return processed > 0 ? (double) totalProcessingTime.get() / processed : 0;
    }

    /**
     * 获取成功率
     */
    public double getSuccessRate() {
        int total = processedCount.get() + failedCount.get();
        return total > 0 ? (double) processedCount.get() / total * 100 : 0;
    }

    /**
     * 获取失败率
     */
    public double getFailureRate() {
        int total = processedCount.get() + failedCount.get();
        return total > 0 ? (double) failedCount.get() / total * 100 : 0;
    }

    /**
     * 获取重试率
     */
    public double getRetryRate() {
        int processed = processedCount.get();
        return processed > 0 ? (double) retriedCount.get() / processed * 100 : 0;
    }

    /**
     * 获取完成率（相对于发送数）
     */
    public double getCompletionRate() {
        int sent = sentCount.get();
        return sent > 0 ? (double) processedCount.get() / sent * 100 : 0;
    }

    /**
     * 获取活跃消费者数量
     */
    public int getActiveConsumerCount() {
        return consumerActivity.size();
    }

    /**
     * 获取消费者活动统计
     */
    public ConcurrentHashMap<String, AtomicInteger> getConsumerActivity() {
        return consumerActivity;
    }

    /**
     * 获取最后活动时间
     */
    public LocalDateTime getLastActivityTime() {
        return lastActivityTime;
    }

    // ================== 私有辅助方法 ==================

    private void updateLastActivityTime() {
        lastActivityTime = LocalDateTime.now();
    }

    private void updateMinProductionTime(long time) {
        long current;
        do {
            current = minProductionTime.get();
        } while (time < current && !minProductionTime.compareAndSet(current, time));
    }

    private void updateMaxProductionTime(long time) {
        long current;
        do {
            current = maxProductionTime.get();
        } while (time > current && !maxProductionTime.compareAndSet(current, time));
    }

    private void updateMinProcessingTime(long time) {
        long current;
        do {
            current = minProcessingTime.get();
        } while (time < current && !minProcessingTime.compareAndSet(current, time));
    }

    private void updateMaxProcessingTime(long time) {
        long current;
        do {
            current = maxProcessingTime.get();
        } while (time > current && !maxProcessingTime.compareAndSet(current, time));
    }

    // ================== 重置方法 ==================

    /**
     * 重置所有统计数据
     */
    public void reset() {
        sentCount.set(0);
        processedCount.set(0);
        failedCount.set(0);
        retriedCount.set(0);
        totalProductionTime.set(0);
        totalProcessingTime.set(0);
        minProductionTime.set(Long.MAX_VALUE);
        maxProductionTime.set(0);
        minProcessingTime.set(Long.MAX_VALUE);
        maxProcessingTime.set(0);
        consumerActivity.clear();
        lastActivityTime = LocalDateTime.now();
    }

    // ================== 字符串表示 ==================

    @Override
    public String toString() {
        return String.format(
                "QueueStatistics{name='%s', sent=%d, processed=%d, failed=%d, retried=%d, " +
                "avgProcessTime=%.2fms, successRate=%.1f%%}",
                queueName, sentCount.get(), processedCount.get(), failedCount.get(),
                retriedCount.get(), getAverageProcessingTime(), getSuccessRate()
        );
    }

    /**
     * 获取详细统计报告
     */
    public String getDetailedReport() {
        StringBuilder report = new StringBuilder();
        report.append(String.format("队列: %s\n", queueName));
        report.append(String.format("  最后活动时间: %s\n", lastActivityTime));
        report.append("  消息统计:\n");
        report.append(String.format("    发送数: %d\n", sentCount.get()));
        report.append(String.format("    处理数: %d\n", processedCount.get()));
        report.append(String.format("    失败数: %d\n", failedCount.get()));
        report.append(String.format("    重试数: %d\n", retriedCount.get()));

        report.append("  时间统计:\n");
        report.append(String.format("    平均生产时间: %.2f ms\n", getAverageProductionTime()));
        report.append(String.format("    平均处理时间: %.2f ms\n", getAverageProcessingTime()));

        report.append("  性能指标:\n");
        report.append(String.format("    成功率: %.2f%%\n", getSuccessRate()));
        report.append(String.format("    失败率: %.2f%%\n", getFailureRate()));
        report.append(String.format("    重试率: %.2f%%\n", getRetryRate()));
        report.append(String.format("    完成率: %.2f%%\n", getCompletionRate()));

        if (!consumerActivity.isEmpty()) {
            report.append("  消费者活动:\n");
            consumerActivity.forEach((consumer, count) ->
                    report.append(String.format("    %s: %d 次\n", consumer, count.get())));
        }

        return report.toString();
    }
}